<script setup lang="ts">
import { ref, watch } from 'vue'

import icon from "@/utils/icons"
import { NInput, NCard, NGrid, NGridItem, useMessage, NIcon, NP, NSpin } from "naive-ui"
import { useIntersectionObserver, useWindowSize } from '@vueuse/core'
import CustomIcon from '@/components/CustomIcon'

// 组件逻辑
const { height } = useWindowSize()
const message = useMessage()



const iconList = ref<string[]>([]);
const pageSize = 70; // 每页加载的数量
let currentPage = 0;
const searchQuery = ref('');
const isLoading = ref(false)
const hasMore = ref(true)


function * chunkObjectKeys<T extends object>(obj: T, chunkSize: number = 14): Generator<string[], void, unknown> {
  const entries = Object.entries(obj);
  for (let i = 0; i < entries.length; i += chunkSize) {
    const chunk = entries.slice(i, i + chunkSize);
    const keys = chunk.map(([key]) => key); // 提取键
    yield keys;
  }
}

function loadNextPage() {
  let iterator: never;
  if (searchQuery.value) {
    const filteredKeys = Object.keys(icon).filter(key => key.toLowerCase().includes(searchQuery.value.toLowerCase()));
    iterator = chunkObjectKeys(Object.fromEntries(filteredKeys.map(key => [key, icon[key]])), pageSize);
  } else {
    iterator = chunkObjectKeys(icon, pageSize);
  }

  let result = iterator.next();
  let pageCount = 0;
  while (!result.done && pageCount <= currentPage) {
    if (pageCount === currentPage) {
      iconList.value = [...iconList.value, ...result.value];
    }
    result = iterator.next();
    pageCount++;
  }
  currentPage++;
}

// 监听搜索查询变化
watch(searchQuery, () => {
  currentPage = 0;
  iconList.value = [];
  loadNextPage();
});
// 初始加载第一页
loadNextPage();

// 使用 Intersection Observer 进行懒加载
const loadMoreTrigger = ref(null);
useIntersectionObserver(
  loadMoreTrigger,
  ([{isIntersecting}]) => {
    if (isIntersecting) {
      loadNextPage();
    }
  },
  {threshold: 0.1}
);
//复制图标
const copyIcon = (icon_name: string) => {
  navigator.clipboard.writeText(icon_name)
    .then(() => {
      message.success('复制图标成功');
    })
    .catch(() => {
      message.error('复制图标失败');
    });
}
</script>

<template>
  <div class="icon-browser">
    <n-card class="search-bar">
      <n-input
        v-model:value="searchQuery"
        placeholder="输入图标名称进行模糊查询..."
        clearable
        :loading="isLoading"
      >
        <template #prefix>
          <n-icon :component="icon['ant-SearchOutlined']" />
        </template>
      </n-input>
    </n-card>

    <div class="icon-container" :style="{ height: `${height - 100}px` }">
      <n-grid
        cols="2 s:3 m:4 l:5 xl:6 2xl:7"
        responsive="screen"
        :x-gap="12"
        :y-gap="12"
      >
        <n-grid-item v-for="item in iconList" :key="item">
          <n-card hoverable :bordered="false" @click="copyIcon(item)">
            <div class="icon-item">

              <custom-icon :component="item" size="28" />
              <n-p class="icon-name" truncate>{{ item }}</n-p>
            </div>
          </n-card>
        </n-grid-item>
      </n-grid>
      <div v-if="isLoading" class="loading-indicator">
        <n-spin size="small" />
      </div>
      <div
        ref="loadMoreTrigger"
        class="load-more-trigger"
        :style="{ visibility: hasMore ? 'visible' : 'hidden' }"
      />
    </div>
  </div>
</template>

<style scoped lang="scss">
.icon-browser {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.search-bar {
  margin-bottom: 16px;
}

.icon-container {
  overflow-y: auto;
  padding: 8px;
}

.icon-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 12px 8px;
  cursor: pointer;
  transition: all 0.2s;
  height: 90px;

  &:hover {
    transform: scale(1.05);
  }

  .n-icon {
    margin-bottom: 8px;
    color: var(--primary-color);
  }

  .icon-name {
    font-size: 12px;
    text-align: center;
    margin: 0;
    width: 100%;
    color: var(--text-color);
  }
}

.loading-indicator {
  display: flex;
  justify-content: center;
  padding: 16px;
}

.load-more-trigger {
  height: 1px;
  margin-top: -1px;
}
</style>
